package cn.maidouya.hrm.userdetailservice;

import cn.maidouya.hrm.authdto.AuthSystemLongUser;
import cn.maidouya.hrm.constant.SystemLoginConstant;
import cn.maidouya.hrm.domain.LoginUser;
import cn.maidouya.hrm.domain.Permission;
import cn.maidouya.hrm.feignClient.ISystemLoginUserFeign;
import cn.maidouya.hrm.mapper.LoginUserMapper;
import cn.maidouya.hrm.util.AjaxResult;
import cn.maidouya.hrm.util.ValidUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service // 交给spring管理
public class UserDetailService implements UserDetailsService{
    @Autowired
    private LoginUserMapper loginUserMapper;
    @Autowired
    private ISystemLoginUserFeign systemLoginUserFeign;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 创建loginUser保存username属性值  查询用户名是否存在
        LoginUser loginUser = new LoginUser();
            loginUser.setUsername(username);
            loginUser = loginUserMapper.selectOne(loginUser);
            // 断言抛出异常
            ValidUtils.assertNotNull(loginUser,"用户不存在！");
        // 2. 查询用户权限
        List<Permission> list =  loginUserMapper.getPermission(loginUser.getId());
        // 3. 创建集合泛型为SimpleGrantedAuthority
        ArrayList<SimpleGrantedAuthority> authors = new ArrayList<SimpleGrantedAuthority>();
            // 遍历结合数据
        list.stream().forEach(permission -> {
         // 4. 装SimpleGrantedAuthority保存交给springsecurity管理
            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permission.getSn());
            authors.add(simpleGrantedAuthority);
        });

        System.out.println("管理员" + loginUser);
        // 管理员才有该权限   通过拦截器拦截生成临时token授权  只有超级管理员有该权限
        if (loginUser.getType() == 0){
            // 这里还没有生成token就去查询了system数据就会出现报错，用interceptor拦截器拦截生成临时的token访问system
                AjaxResult ajaxResult = systemLoginUserFeign.loadLoginUserById(loginUser.getId());
                // 调用feign接口校验是否为空
                ValidUtils.assertNotNull(ajaxResult.getResultObj(),"授权失败！");
                // ajaxResult是对象，强制转换的话是一坨字符串，ajaxResult在AjaxResult中是成员变量
                // 所以利用linkedHashmap底层实现转换linkedhashmap格式数据
                LinkedHashMap map = (LinkedHashMap<String,String>)ajaxResult.getResultObj();
                AuthSystemLongUser authSystemLongUser = new AuthSystemLongUser();
                // 使用源码出现异常尽量用try接收异常  拷贝数据
                try {
                    BeanUtils.populate(authSystemLongUser,map);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

                // 登录对象放入redis中
                redisTemplate.opsForValue().set(SystemLoginConstant.SYSTEM_LOGINUSER_KEY+loginUser.getUsername(),authSystemLongUser);
        }
        // 5. 封装对象交个security管理
        User user = new User(loginUser.getUsername(),loginUser.getPassword(),authors);

        return user;
    }
}
